package com.szh.cloud.file.service.impl;

import com.obs.services.ObsClient;
import com.obs.services.model.ObjectListing;
import com.obs.services.model.ObsObject;
import com.obs.services.model.TemporarySignatureRequest;
import com.obs.services.model.TemporarySignatureResponse;
import com.szh.cloud.file.entity.SearFileEntity;
import com.szh.cloud.file.repository.FileDao;
import com.szh.cloud.file.service.FileService;
import com.szh.cloud.login.entity.LoginUserEntity;
import com.szh.cloud.mybatis.entity.PtFileEntity;
import com.szh.cloud.mybatis.flexigrid.FlexResEntity;
import com.szh.cloud.mybatis.flexigrid.PagingBean;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService {
    private static Log logger= LogFactory.getLog(FileServiceImpl.class);

    @Value("${end.point}")
    private String endpoint = "";
    @Value("${ak}")
    private String ak = "";
    @Value("${sk}")
    private String sk = "";
    @Value("${bucket.name}")
    private String bucketName = "";
    @Resource
    private FileDao fileDao;


    @Override
    public void synchFileData(){
        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        ObjectListing list = obsClient.listObjects(bucketName);
        List<ObsObject> listObjects = list.getObjects();
        PtFileEntity ptFileEntity;
        Long fileSize;
        String filePath;
        LoginUserEntity entity = (LoginUserEntity) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        String fileName="";
        List<PtFileEntity> ptFileEntityList=new ArrayList<>();
        List<PtFileEntity> ptFileEntityListDb=fileDao.queryFileListAll();
        boolean flag=false;
        for(ObsObject obsObject:listObjects){

            filePath=obsObject.getObjectKey();
            fileSize = obsObject.getMetadata().getContentLength();
/*           logger.info("obsKey:" + filePath);
            logger.info("obsSize:" + fileSize);*/
            ptFileEntity=new PtFileEntity();
            ptFileEntityList.add(ptFileEntity);
            flag=false;
            for(PtFileEntity dbItem:ptFileEntityListDb){
                if(filePath.equals(dbItem.getDelFlag())){
                    ptFileEntity.setFileUuid(dbItem.getFileUuid());
                    ptFileEntity.setDelFlag(dbItem.getDelFlag());
                    flag=true;
                    break;
                }
            }
            if (!flag){
                ptFileEntity.setFileUuid(UUID.randomUUID().toString());
            }

            ptFileEntity.setFileCapacity(fileSize);
            ptFileEntity.setFilePath(filePath);
            ptFileEntity.setUserUuid(entity.getUserUuid());

            if(fileSize==0){
                ptFileEntity.setFileType(FILE_TYPR_DIR);
            }else {
                ptFileEntity.setFileType(FILE_TYPR_FILE);
            }
            fileName=getFileName(filePath);
            ptFileEntity.setFileName(fileName);
 //           logger.info("ptFile:"+ptFileEntity);
        }
        //查找parentid
        for(PtFileEntity child:ptFileEntityList){
            for (PtFileEntity parent:ptFileEntityList){
                if (child.getFileUuid().equals(parent.getFileUuid())){
                    continue;
                }
                if (child.getFilePath().indexOf(parent.getFilePath())==0){
                    child.setParentUuid(parent.getFileUuid());
                }
            }
        }
        logger.info("list:"+ptFileEntityList);
        fileDao.deleteFileInfo();
        //保存数据
        for (PtFileEntity item:ptFileEntityList){
            fileDao.insertFileInfo(item);
        }

    }

    /**老师
     * 获取文件路径
     * @param filePath
     * @return
     */
    private String getFileName(String filePath){
        String fileName=filePath;
        if(!filePath.contains(File_SEPARATOR)){
            String[] fileNameArray = filePath.split(File_SEPARATOR);
            fileName=fileNameArray[fileNameArray.length-1];
        }
        return fileName;
    }

    @Override
    public FlexResEntity<PtFileEntity> queryFileListByPage(SearFileEntity entity, PagingBean paging) {
        // 获取当前目录路径
        PtFileEntity currentFolder = fileDao.queryFileInfoById(entity.getFileUuid());
        String currentPath = (currentFolder != null) ? currentFolder.getFilePath() : "";

        // 添加路径前缀匹配（搜索当前目录及子目录）
        if(!StringUtils.isEmpty(currentPath)){
            entity.setFilePathLike(currentPath + "%");
        }
        FlexResEntity<PtFileEntity> flexResEntity=new FlexResEntity<PtFileEntity>();
        flexResEntity.setPage(paging.getPage());
        paging.deal(PtFileEntity.class);
        List<PtFileEntity> list= fileDao.queryFileListByPage(entity,paging);
        flexResEntity.setRawRecords(list);
        Integer total=fileDao.queryFileListTotal(entity);
        flexResEntity.setTotal(total);
        flexResEntity.deal();
        return flexResEntity;
    }

    @Override
    public PtFileEntity queryParentFileById(String fileUuid) {
        PtFileEntity local = fileDao.queryFileInfoById(fileUuid);
        if(local == null){
            return null;
        }
        PtFileEntity parent = fileDao.queryFileInfoById(local.getParentUuid());
        return parent;
    }

    @Override
    public void mkdir(String folderName, String parentName) {
        String filePath=folderName;
        if(!File_SEPARATOR.equals(parentName)){
            filePath=parentName+folderName;
        }
        filePath+=File_SEPARATOR;
        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        InputStream inputStream =new ByteArrayInputStream(new byte[0]);
        obsClient.putObject(bucketName,filePath,inputStream);
        synchFileData();
    }

    @Override
    public void uploadFile(String fileName, String parentPath, InputStream inputStream) {
        String filePath=fileName;
        if(!File_SEPARATOR.equals(parentPath)){
            filePath=parentPath+fileName;
        }
        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        obsClient.putObject(bucketName,filePath,inputStream);
        synchFileData();
    }

    //下载文件
    @Override
    public ResponseEntity<byte[]> downloadFile(String fileUuid) {
        PtFileEntity fileEntity = fileDao.queryFileInfoById(fileUuid);
        if (fileEntity == null){
            return null;
        }

        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        ObsObject obsObject = obsClient.getObject(bucketName,fileEntity.getFilePath());
        InputStream inputStream = obsObject.getObjectContent();

        byte[] bock =  new byte[1024];
        int length = 0;
        byte [] fileByte = null;
        try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()){
            while ((length = inputStream.read(bock)) > 0){
                byteArrayOutputStream.write(bock,0,length);
                byteArrayOutputStream.flush();
            }
            fileByte = byteArrayOutputStream.toByteArray();
        }catch (IOException e){

        }

        HttpHeaders headers =
                new HttpHeaders();
        headers.setContentDispositionFormData("attachment",
                fileEntity.getFileName());//告知浏览器以下载方式打开
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//设置 MIME 类型
        return new ResponseEntity<byte[]>(
                fileByte,
                headers,
                HttpStatus.CREATED);
    }

    @Override
    public String queryShareUrl(String fileUuid, Integer shareDate) {
        PtFileEntity fileEntity = fileDao.queryFileInfoById(fileUuid);
        if(fileEntity == null){
            return "";
        }
        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(fileEntity.getFilePath());
        request.setRequestDate(new Date());
        request.setExpires(SHARE_DATE_UTIL * shareDate);
        TemporarySignatureResponse signature = obsClient.createTemporarySignature(request);
        String url = signature.getSignedUrl();
        return url;
    }

    @Override
    public String queryFileUrl(String fileUuid) {
        PtFileEntity fileEntity = (PtFileEntity) fileDao.queryFileInfoById(fileUuid);
        if(fileEntity == null){
            return "";
        }
        ObsClient obsClient = new ObsClient(ak, sk, endpoint);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(fileEntity.getFilePath());
        request.setRequestDate(new Date());
        request.setExpires(SHARE_DATE_UTIL);
        TemporarySignatureResponse signature = obsClient.createTemporarySignature(request);
        String url = signature.getSignedUrl();
        return url;
    }

    @Override
    public void copyPasteFile(String fileUuidArray, String descDir) {
        String[] fileUuids = fileUuidArray.split(",");
        List<PtFileEntity> ptFileEntityList = fileDao.queryFileListByArray(fileUuids);
        String descPath = "";
        ObsClient obsClient = new ObsClient(ak,sk,endpoint);
        ObsObject obsObject;
        InputStream inputStream;
        for(PtFileEntity item:ptFileEntityList){
            descDir = item.getFileName();
            if(File_SEPARATOR.equals(descDir)){
                descPath = item.getFileName();
            }else{
                descPath = descDir + item.getFileName();
            }
            obsObject = obsClient.getObject(bucketName,item.getFilePath());
            inputStream = obsObject.getObjectContent();
            obsClient.putObject(bucketName,descPath,inputStream);

        }
        synchFileData();
    }
}
